[IA64] Create Xen machine vector
authorAlex Williamson <alex.williamson@hp.com>
Mon, 7 May 2007 14:52:12 +0000 (08:52 -0600)
committerAlex Williamson <alex.williamson@hp.com>
Mon, 7 May 2007 14:52:12 +0000 (08:52 -0600)
This allows us to easily switch between hardware or software iommu and
simple remapping.  The Xen machine vector is only intended for domU
guests at this point.

Signed-off-by: Alex Williamson <alex.williamson@hp.com>
linux-2.6-xen-sparse/arch/ia64/Kconfig
linux-2.6-xen-sparse/arch/ia64/Makefile
linux-2.6-xen-sparse/arch/ia64/kernel/acpi.c
linux-2.6-xen-sparse/arch/ia64/xen/machvec.c [new file with mode: 0644]
linux-2.6-xen-sparse/arch/ia64/xen/xen_dma.c [new file with mode: 0644]
linux-2.6-xen-sparse/include/asm-ia64/machvec.h
linux-2.6-xen-sparse/include/asm-ia64/machvec_xen.h [new file with mode: 0644]

index e665b7c391ab2365281afac83e76b7e991d554f9..4991dd4a2b8359bb31cc1279fa3f592c2c47f190 100644 (file)
@@ -161,6 +161,10 @@ config IA64_SGI_SN2
 config IA64_HP_SIM
        bool "Ski-simulator"
 
+config IA64_XEN
+       bool "Xen guest"
+       depends on XEN
+
 endchoice
 
 choice
index 399209be32c9927f6ba83adf500a2156d41ef169..9c7c05626b2b5fca265eacdd202708769d44ca1a 100644 (file)
@@ -60,6 +60,7 @@ core-$(CONFIG_IA64_DIG)       += arch/ia64/dig/
 core-$(CONFIG_IA64_GENERIC)    += arch/ia64/dig/
 core-$(CONFIG_IA64_HP_ZX1)     += arch/ia64/dig/
 core-$(CONFIG_IA64_HP_ZX1_SWIOTLB) += arch/ia64/dig/
+core-$(CONFIG_IA64_XEN)                += arch/ia64/dig/
 core-$(CONFIG_IA64_SGI_SN2)    += arch/ia64/sn/
 core-$(CONFIG_XEN)             += arch/ia64/xen/
 
index 0176556aeeccbf28fa6c14a9c99f07f51750d9ae..54e2fb8ab7995c286d4ad1d393b6dffe3de6e373 100644 (file)
@@ -109,6 +109,10 @@ const char *acpi_get_sysname(void)
                return "hpzx1";
        } else if (!strcmp(hdr->oem_id, "SGI")) {
                return "sn2";
+#ifdef CONFIG_XEN
+       } else if (is_running_on_xen() && !strcmp(hdr->oem_id, "XEN")) {
+               return "xen";
+#endif
        }
 
        return "dig";
@@ -123,6 +127,8 @@ const char *acpi_get_sysname(void)
        return "sn2";
 # elif defined (CONFIG_IA64_DIG)
        return "dig";
+# elif defined (CONFIG_IA64_XEN)
+       return "xen";
 # else
 #      error Unknown platform.  Fix acpi.c.
 # endif
diff --git a/linux-2.6-xen-sparse/arch/ia64/xen/machvec.c b/linux-2.6-xen-sparse/arch/ia64/xen/machvec.c
new file mode 100644 (file)
index 0000000..4ad588a
--- /dev/null
@@ -0,0 +1,4 @@
+#define MACHVEC_PLATFORM_NAME           xen
+#define MACHVEC_PLATFORM_HEADER         <asm/machvec_xen.h>
+#include <asm/machvec_init.h>
+
diff --git a/linux-2.6-xen-sparse/arch/ia64/xen/xen_dma.c b/linux-2.6-xen-sparse/arch/ia64/xen/xen_dma.c
new file mode 100644 (file)
index 0000000..5962e73
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2007 Hewlett-Packard Development Company, L.P.
+ *     Alex Williamson <alex.williamson@hp.com>
+ *
+ * Basic DMA mapping services for Xen guests.
+ * Based on arch/i386/kernel/pci-dma-xen.c.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/mm.h>
+#include <asm/scatterlist.h>
+
+#define IOMMU_BUG_ON(test)                                     \
+do {                                                           \
+       if (unlikely(test)) {                                   \
+               printk(KERN_ALERT "Fatal DMA error!\n");        \
+               BUG();                                          \
+       }                                                       \
+} while (0)
+
+
+/*
+ * This should be broken out of swiotlb and put in a common place
+ * when merged with upstream Linux.
+ */
+static inline int
+address_needs_mapping(struct device *hwdev, dma_addr_t addr)
+{
+       dma_addr_t mask = 0xffffffff;
+
+       /* If the device has a mask, use it, otherwise default to 32 bits */
+       if (hwdev && hwdev->dma_mask)
+               mask = *hwdev->dma_mask;
+       return (addr & ~mask) != 0;
+}
+
+int
+xen_map_sg(struct device *hwdev, struct scatterlist *sg, int nents,
+          int direction)
+{
+       int i;
+
+       for (i = 0 ; i < nents ; i++) {
+               sg[i].dma_address = page_to_bus(sg[i].page) + sg[i].offset;
+               sg[i].dma_length  = sg[i].length;
+
+               IOMMU_BUG_ON(address_needs_mapping(hwdev, sg[i].dma_address));
+       }
+
+       return nents;
+}
+EXPORT_SYMBOL(xen_map_sg);
+
+void
+xen_unmap_sg(struct device *hwdev, struct scatterlist *sg, int nents,
+            int direction)
+{
+}
+EXPORT_SYMBOL(xen_unmap_sg);
+
+int
+xen_dma_mapping_error(dma_addr_t dma_addr)
+{
+       return 0;
+}
+EXPORT_SYMBOL(xen_dma_mapping_error);
+
+int
+xen_dma_supported(struct device *dev, u64 mask)
+{
+       return 1;
+}
+EXPORT_SYMBOL(xen_dma_supported);
+
+void *
+xen_alloc_coherent(struct device *dev, size_t size,
+                  dma_addr_t *dma_handle, gfp_t gfp)
+{
+       unsigned long vaddr;
+       unsigned int order = get_order(size);
+
+       vaddr = __get_free_pages(gfp, order);
+
+       if (!vaddr)
+               return NULL;
+
+       if (xen_create_contiguous_region(vaddr, order,
+                                        dev->coherent_dma_mask)) {
+               free_pages(vaddr, order);
+               return NULL;
+       }
+
+       memset((void *)vaddr, 0, size);
+       *dma_handle = virt_to_bus((void *)vaddr);
+
+       return (void *)vaddr;
+}
+EXPORT_SYMBOL(xen_alloc_coherent);
+
+void
+xen_free_coherent(struct device *dev, size_t size,
+                     void *vaddr, dma_addr_t dma_handle)
+{
+       unsigned int order =  get_order(size);
+
+       xen_destroy_contiguous_region((unsigned long)vaddr, order);
+       free_pages((unsigned long)vaddr, order);
+}
+EXPORT_SYMBOL(xen_free_coherent);
+
+dma_addr_t
+xen_map_single(struct device *dev, void *ptr, size_t size,
+              int direction)
+{
+       dma_addr_t dma_addr = virt_to_bus(ptr);
+
+       IOMMU_BUG_ON(range_straddles_page_boundary(ptr, size));
+       IOMMU_BUG_ON(address_needs_mapping(dev, dma_addr));
+
+       return dma_addr;
+}
+EXPORT_SYMBOL(xen_map_single);
+
+void
+xen_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
+                int direction)
+{
+}
+EXPORT_SYMBOL(xen_unmap_single);
index 15b545a897a4b6a05843f12f4691c37acad46885..e712d90b198f1ab6df1a8c7af66c9f692494e7e0 100644 (file)
@@ -108,6 +108,8 @@ extern void machvec_tlb_migrate_finish (struct mm_struct *);
 #  include <asm/machvec_hpzx1_swiotlb.h>
 # elif defined (CONFIG_IA64_SGI_SN2)
 #  include <asm/machvec_sn2.h>
+# elif defined (CONFIG_IA64_XEN)
+#  include <asm/machvec_xen.h>
 # elif defined (CONFIG_IA64_GENERIC)
 
 # ifdef MACHVEC_PLATFORM_HEADER
diff --git a/linux-2.6-xen-sparse/include/asm-ia64/machvec_xen.h b/linux-2.6-xen-sparse/include/asm-ia64/machvec_xen.h
new file mode 100644 (file)
index 0000000..cdffdfb
--- /dev/null
@@ -0,0 +1,37 @@
+#ifndef _ASM_IA64_MACHVEC_XEN_h
+#define _ASM_IA64_MACHVEC_XEN_h
+
+extern ia64_mv_setup_t                 dig_setup;
+extern ia64_mv_dma_alloc_coherent      xen_alloc_coherent;
+extern ia64_mv_dma_free_coherent       xen_free_coherent;
+extern ia64_mv_dma_map_single          xen_map_single;
+extern ia64_mv_dma_unmap_single                xen_unmap_single;
+extern ia64_mv_dma_map_sg              xen_map_sg;
+extern ia64_mv_dma_unmap_sg            xen_unmap_sg;
+extern ia64_mv_dma_supported           xen_dma_supported;
+extern ia64_mv_dma_mapping_error       xen_dma_mapping_error;
+
+/*
+ * This stuff has dual use!
+ *
+ * For a generic kernel, the macros are used to initialize the
+ * platform's machvec structure.  When compiling a non-generic kernel,
+ * the macros are used directly.
+ */
+#define platform_name                          "xen"
+#define platform_setup                         dig_setup
+#define platform_dma_init                      machvec_noop
+#define platform_dma_alloc_coherent            xen_alloc_coherent
+#define platform_dma_free_coherent             xen_free_coherent
+#define platform_dma_map_single                        xen_map_single
+#define platform_dma_unmap_single              xen_unmap_single
+#define platform_dma_map_sg                    xen_map_sg
+#define platform_dma_unmap_sg                  xen_unmap_sg
+#define platform_dma_sync_single_for_cpu       machvec_dma_sync_single
+#define platform_dma_sync_sg_for_cpu           machvec_dma_sync_sg
+#define platform_dma_sync_single_for_device    machvec_dma_sync_single
+#define platform_dma_sync_sg_for_device                machvec_dma_sync_sg
+#define platform_dma_supported                 xen_dma_supported
+#define platform_dma_mapping_error             xen_dma_mapping_error
+
+#endif /* _ASM_IA64_MACHVEC_XEN_h */